package net.lab1024.sa.admin.util;

import jdk.nashorn.internal.runtime.logging.Logger;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.base.common.code.ErrorCode;
import net.lab1024.sa.base.common.code.SystemErrorCode;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.module.support.redis.RedisService;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Logger
public class CmdExecutor {


    // WPS各组件默认路径（可根据实际安装目录修改）
    //private static final String DEFAULT_WPS_PATH = "D:\\software\\WPS_Office\\12.1.0.22529\\office6\\";
    private static final String DEFAULT_WPS_PATH = "C:\\home\\WPS\\WPS_Office\\12.1.0.22525\\office6\\";

    private static final String WPS_WORD_EXE = "wps.exe";       // Word文件处理程序
    private static final String WPS_EXCEL_EXE = "et.exe";        // Excel文件处理程序
    private static final String WPS_PDF_EXE = "wpspdf.exe";      // PDF文件处理程序
    private static final String WPS_IMAGE_VIEWER = "wpsviewer.exe"; // 图片查看程序
    //private static final String WPS_IMAGE_VIEWER = "wps.exe"; // 图片查看程序


    /**
     * 根据文件类型自动选择对应的WPS程序进行打印
     *
     * @param filePath 要打印的文件路径
     * @param printerName 打印机名称
     * @param copies 打印份数
     * @return 命令执行结果
     */
    public static ResponseDTO<String> printFile(String filePath,
                                                String printerName, int copies) {
        // 验证文件是否存在
        File targetFile = new File(filePath);
        if (!targetFile.exists() || !targetFile.isFile()) {
            return  ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR,"文件不存在: " + filePath) ;
        }

        // 验证打印份数
        if (copies <= 0) {
            return  ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR,"打印份数必须大于0") ;
        }

        // 确定WPS安装目录
        String wpsPath = DEFAULT_WPS_PATH;

        // 获取文件后缀名
        String fileExt = getFileExtension(filePath).toLowerCase();

        // 根据文件类型选择对应的执行程序和命令
        String wpsExe;
        String commandTemplate;
        wpsExe = wpsPath + WPS_PDF_EXE;
        commandTemplate = "start /b %s /p \"%s\" /printer \"%s\" /copies %d";
//        switch (fileExt) {
//            case "pdf":
//                wpsExe = wpsPath + WPS_PDF_EXE;
//                commandTemplate = "start /b %s /p \"%s\" /printer \"%s\" /copies %d";
//                break;
//            case "doc":
//            case "docx":
//                wpsExe = wpsPath + WPS_PDF_EXE;
//                commandTemplate = "start /b %s /p \"%s\" /printer \"%s\" /copies %d";
//                break;
//            case "xls":
//            case "xlsx":
//                wpsExe = wpsPath + WPS_EXCEL_EXE;
//                commandTemplate = "start /b %s /p \"%s\" /printer \"%s\" /copies %d";
//                break;

//            case "jpg":
//            case "jpeg":
//            case "png":
//            case "gif":
//            case "bmp":
//                wpsExe = wpsPath + WPS_IMAGE_VIEWER;
//                commandTemplate = "start /b %s /p \"%s\" /printer \"%s\" /copies %d";
//                break;
//            default:
//                return  ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR,"不支持的文件类型: " + fileExt) ;
//
//        }

        // 获取当前默认打印机
        String originalDefaultPrinter = getDefaultPrinter();
        if (originalDefaultPrinter == null) {
            log.error("无法获取当前默认打印机");
        }

        try {
            // 如果目标打印机不是默认打印机，则临时修改
            if (!originalDefaultPrinter.equals(printerName)) {
                log.info("临时将默认打印机设置为：" + printerName);
                if (!setDefaultPrinter(printerName)) {
                    log.error("无法设置默认打印机为：" + printerName);
                }
            }

        } catch (Exception e) {
            log.error("打印过程中发生错误：" + e.getMessage());
            e.printStackTrace();
        } finally {
            // 恢复原来的默认打印机
//            if (!originalDefaultPrinter.equals(printerName)) {
//                log.info("恢复默认打印机为：" + originalDefaultPrinter);
//                setDefaultPrinter(originalDefaultPrinter);
//            }
        }

        // 验证WPS执行程序是否存在
        File wpsExeFile = new File(wpsExe);
        if (!wpsExeFile.exists()) {
            return  ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR,"WPS程序不存在: " + wpsExe) ;
        }
        // 构建命令
        String command;
        if ("pdf".equals(fileExt)) {
            // PDF支持copies参数
            command = String.format(commandTemplate, wpsExe, filePath, printerName, copies);
        } else {
            // 其他类型通过WPS内部设置处理份数
            command = String.format(commandTemplate, wpsExe, filePath, printerName, copies);
        }
        log.info(command);
        // 执行命令
        //executeWindowsCommand(command);
         executeCommand(command, copies);
        //executeCommand(command, null, true);
        return ResponseDTO.ok();
    }


    /**
     * 获取当前默认打印机
     */
    private static String getDefaultPrinter() {
        try {
            Process process = Runtime.getRuntime().exec("wmic printer get name,default");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));

            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.contains("TRUE") && !line.contains("Name")) {
                    return line.replace("TRUE", "").trim();
                }
            }
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 设置默认打印机
     */
    private static boolean setDefaultPrinter(String printerName) {
        try {
            String command = String.format("wmic printer where name='%s' call setdefaultprinter",
                    printerName.replace("'", "\\'"));
            Process process = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", command});
            return process.waitFor() == 0;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 执行CMD命令
     */
    private static String executeCommand(String command, int copies) {
        StringBuilder result = new StringBuilder();
        Process process = null;
        BufferedReader reader = null;

        try {
            // 构建命令列表
            List<String> commands = new ArrayList<>();
            commands.add("cmd");
            commands.add("/c");
            commands.add(command);

            // 创建进程构建器
            ProcessBuilder pb = new ProcessBuilder(commands);
            pb.redirectErrorStream(true);

            // 启动进程
            process = pb.start();

            // 读取输出
            InputStream inputStream = process.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, "GBK"));

            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line).append("\n");
            }

            // 等待命令执行完成
            int exitCode = process.waitFor();
            result.append("命令执行结束，退出码：").append(exitCode).append("\n");
            result.append(String.format("打印文件，份数：%d", copies));

        } catch (IOException | InterruptedException e) {
            result.append("命令执行出错：").append(e.getMessage()).append("\n");
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (process != null) {
                process.destroy();
            }
        }
        log.info(command);
        log.info(result.toString());
        return result.toString();
    }

    /**
     * 获取文件后缀名
     */
    private static String getFileExtension(String filePath) {
        int lastDotIndex = filePath.lastIndexOf('.');
        if (lastDotIndex > 0 && lastDotIndex < filePath.length() - 1) {
            return filePath.substring(lastDotIndex + 1);
        }
        return "";
    }
    /**
     * 执行Windows命令行命令
     *
     * @param command 要执行的CMD命令字符串
     * @param workingDir 工作目录（null则使用当前目录）
     * @param waitForCompletion 是否等待命令执行完成
     * @return 命令执行结果信息
     */
    public static String executeCommand(String command, String workingDir, boolean waitForCompletion) {
        StringBuilder result = new StringBuilder();
        Process process = null;
        BufferedReader reader = null;

        try {
            // 构建命令列表，使用cmd /c 执行命令
            List<String> commands = new ArrayList<>();
            commands.add("cmd");
            commands.add("/c");
            commands.add(command);

            // 创建进程构建器
            ProcessBuilder processBuilder = new ProcessBuilder(commands);

            // 设置工作目录
            if (workingDir != null && !workingDir.trim().isEmpty()) {
                processBuilder.directory(new java.io.File(workingDir));
                result.append("工作目录: ").append(workingDir).append("\n");
            }

            // 合并错误流到输出流，方便统一处理
            processBuilder.redirectErrorStream(true);

            // 启动进程
            result.append("执行命令: ").append(command).append("\n");
            process = processBuilder.start();

            // 读取命令输出
            InputStream inputStream = process.getInputStream();
            // Windows命令行默认编码为GBK，避免中文乱码
            reader = new BufferedReader(new InputStreamReader(inputStream, "GBK"));

            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line).append("\n");
            }

            // 如果需要等待命令完成，获取退出码
            if (waitForCompletion) {
                int exitCode = process.waitFor();
                result.append("命令执行结束，退出码: ").append(exitCode).append("\n");
                if (exitCode == 0) {
                    result.append("命令执行成功");
                } else {
                    result.append("命令执行失败，退出码非0");
                }
            } else {
                result.append("命令已启动，未等待执行完成");
            }

        } catch (IOException e) {
            result.append("IO异常: ").append(e.getMessage()).append("\n");
            e.printStackTrace();
        } catch (InterruptedException e) {
            result.append("命令执行被中断: ").append(e.getMessage()).append("\n");
            Thread.currentThread().interrupt(); // 恢复中断状态
        } finally {
            // 关闭资源
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (process != null) {
                process.destroy();
            }
        }
    log.info(result.toString());
        return result.toString();
    }


    // 执行CMD命令（针对Windows优化）
    public static CommandResult executeWindowsCommand(String command) {
        return executeWindowsCommand(command, null, 60000);
    }

    // 带工作目录和超时的命令执行
    public static CommandResult executeWindowsCommand(String command, String workingDir, long timeout) {
        Process process = null;
        BufferedReader inputReader = null;
        BufferedReader errorReader = null;

        try {
            // Windows下固定使用cmd.exe执行命令
            String[] cmdArray = {"cmd.exe", "/c", command};

            // 打印执行的命令，便于调试
            log.info("执行Windows命令: " + String.join(" ", cmdArray));

            ProcessBuilder pb = new ProcessBuilder(cmdArray);

            // 设置工作目录
            if (workingDir != null && !workingDir.isEmpty()) {
                File dir = new File(workingDir);
                if (dir.exists() && dir.isDirectory()) {
                    pb.directory(dir);
                } else {
                    log.error("工作目录不存在: " + workingDir);
                }
            }

            // 设置Windows环境变量
            pb.environment().put("PATH", System.getenv("PATH") + ";C:\\Windows\\System32;C:\\Windows");

            // 重定向错误流
            pb.redirectErrorStream(false);

            // 启动进程
            process = pb.start();

            // 处理输入流和错误流（Windows默认使用GBK编码）
            inputReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
            errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "GBK"));

            // 启动线程读取输出，防止缓冲区满导致阻塞
            StreamGobbler inputGobbler = new StreamGobbler(inputReader);
            StreamGobbler errorGobbler = new StreamGobbler(errorReader);

            inputGobbler.start();
            errorGobbler.start();

            // 超时处理线程
            Process finalProcess = process;
            Thread timeoutThread = new Thread(() -> {
                try {
                    Thread.sleep(timeout);
                    if (finalProcess.isAlive()) {
                        finalProcess.destroyForcibly();
                        log.error("命令执行超时，已强制终止");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
            timeoutThread.start();

            // 等待命令执行完成
            int exitCode = process.waitFor();
            timeoutThread.interrupt(); // 取消超时线程

            // 等待输出处理完成
            inputGobbler.join();
            errorGobbler.join();

            return new CommandResult(exitCode, inputGobbler.getOutput(), errorGobbler.getOutput());

        } catch (Exception e) {
            String errorMsg = "命令执行异常: " + e.getMessage();
            log.error(errorMsg);
            return new CommandResult(-1, null, errorMsg);
        } finally {
            // 关闭资源
            try {
                if (inputReader != null) inputReader.close();
                if (errorReader != null) errorReader.close();
                if (process != null) process.destroy();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 流处理线程
    private static class StreamGobbler extends Thread {
        private BufferedReader reader;
        private List<String> output = new ArrayList<>();

        public StreamGobbler(BufferedReader reader) {
            this.reader = reader;
        }

        @Override
        public void run() {
            try {
                String line;
                while ((line = reader.readLine()) != null) {
                    output.add(line);
                    // 调试时可以打开实时输出
                    //log.info("[输出] " + line);
                }
            } catch (IOException e) {
                output.add("流读取错误: " + e.getMessage());
            }
        }

        public List<String> getOutput() {
            return output;
        }
    }

    // 命令结果封装类
    public static class CommandResult {
        private int exitCode;
        private List<String> output;
        private List<String> error;

        public CommandResult(int exitCode, List<String> output, List<String> error) {
            this.exitCode = exitCode;
            this.output = output;
            this.error = error;
        }

        public CommandResult(int exitCode, List<String> output, String errorMsg) {
            this.exitCode = exitCode;
            this.output = output;
            this.error = new ArrayList<>();
            this.error.add(errorMsg);
        }

        public int getExitCode() { return exitCode; }
        public List<String> getOutput() { return output; }
        public List<String> getError() { return error; }
        public boolean isSuccess() { return exitCode == 0; }
    }

    
    
    
}
